// -*-mode:c++; coding:utf-8-*-

#ifndef _XBASE_BASIC_SSTABLE_IPP_
#define _XBASE_BASIC_SSTABLE_IPP_

namespace xbase
{

	template<typename IArchive>
	inline
	bool sstable_trailer::load(IArchive &in)
	{
		in >> m_magic
		   >> m_version
		   >> m_compression_type
		   >> m_data_size
		   >> m_data_zsize
		   >> m_file_size
		   >> m_block_size
		   >> m_data_block_number
		   >> m_data_record_number
		   >> m_index_key_offset
		   >> m_index_offset_offset
		   >> m_timestamp;
		return in.good();
	}

	template<typename OArchive>
	inline
	bool sstable_trailer::save(OArchive &out) const
	{
		out << m_magic
		    << m_version
		    << m_compression_type
		    << m_data_size
		    << m_data_zsize
		    << m_file_size
		    << m_block_size
		    << m_data_block_number
		    << m_data_record_number
		    << m_index_key_offset
		    << m_index_offset_offset
		    << m_timestamp;
		return out.good();
	}

	inline
	bool sstable::check_file_for_read() const {
		if(m_file == fs::BAD_FILE)
		{
			m_file = fs::open(m_real_path, fs::MT_O_RDONLY);
			if(m_file == fs::BAD_FILE)
			{
				LOG(ERROR, "sstable::check_file_for_read open file "
				    << m_real_path << " for reading failed, fs::errno = "
				    << fs::get_errno() << ", sstable real path = "
				    << m_real_path);
				return false;
			}
		}
		return true;
	}

	inline
	bool sstable::check_file_for_write() const {
		if(m_file == fs::BAD_FILE)
		{
			m_file = fs::open(m_real_path, fs::MT_O_WRONLY);
			if(m_file == fs::BAD_FILE)
			{
				LOG(ERROR, "sstable::check_file_for_write open file "
				    << m_real_path << " for writing failed, fs::errno = "
				    << fs::get_errno() << ", sstable real path = "
				    << m_real_path);
				return false;
			}
			// 写文件时，总是往最后写，所以这里定位到文件尾
			const fs::offset_t ret = fs::seek(m_file, 0, fs::ST_SEEK_END);
			if(ret < 0)
			{
				LOG(ERROR, "sstable::check_file_for_write seek file "
				    << m_real_path << " for writing failed, fs::errno = "
				    << fs::get_errno() << ", sstable real path = "
				    << m_real_path);
				return false;
			}
		}
		return true;
	}

	inline
	bool sstable::load_data(const boost::asio::mutable_buffer &buffer,
				fs::offset_t offset) const
	{
		const fs::offset_t seek_ret
			= fs::seek(m_file, offset, fs::ST_SEEK_SET);
		if(seek_ret < 0)
		{
			LOG(ERROR, "sstable::load_data seek file error, fs::errno = "
			    << fs::get_errno() << ", offset = " << offset
			    << ", sstable real path = " << m_real_path);
			return false;
		}
		const fs::ssize_t read_ret = fs::readn(m_file, buffer);
		if(read_ret != static_cast<fs::ssize_t>(boost::asio::buffer_size(buffer)))
		{
			LOG(ERROR, "sstable::load_data read file error, ret = "
			    << read_ret << ", fs::errno = "
			    << fs::get_errno() << ", sstable real path = "
			    << m_real_path);
			return false;
		}
		return true;
	}

} // namespace xbase

#endif	// _XBASE_BASIC_SSTABLE_IPP_
